前言
最近台股看起來真的很強勢,且台灣的防疫到目前為止確實都做得不錯,
那麼正巧近期剛好月報即將公布,那麼就來做個簡單的月營收增加排行吧!
利用 用 C# .NET Core 爬取每月財報 這篇爬下來的資料
這裡希望挑選出營收月增的條件如下:
- 當月營收 > 上個月營收
- 當月營收 > 去年同月份營收
程式部分
後端: .NET Core Web API
前端: Vue.js
後端
建立回傳的Model:
1 2 3 4 5 6 7 8 9 10
| public class MonthRevenueIncrease { public string stock_id { get; set; } public string stock_name { get; set; } public decimal last_month_increase { get; set; } public decimal last_year_increase { get; set; } public int this_revenue { get; set; } public int last_month_revenue { get; set; } public int last_year_revenue { get; set; } }
|
SQL & Repository
這裡設計成可以由使用者選擇年月,方便比較各月月增的狀況
挑選的邏輯這裡直接用SQL解決了,程式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class RevenueRepository { private readonly SqlConnection _conn; private readonly ILogger<RevenueRepository> _logger; public RevenueRepository(ILogger<RevenueRepository> logger, SqlConnection conn) { _logger = logger; _conn = conn; }
public IEnumerable<MonthRevenueIncrease> GetMonthRevenueIncrease(int year, int month) { return _conn.Query<MonthRevenueIncrease>( @"select stockinfo.stock_id, stockinfo.stock_name, (CONVERT (decimal, mr1.revenue)/CONVERT (decimal, mr2.revenue)) last_month_increase, (CONVERT (decimal, mr1.revenue)/CONVERT (decimal, mr3.revenue)) last_year_increase, mr1.revenue this_revenue, mr2.revenue last_month_revenue, mr3.revenue last_year_revenue from MonthReport mr1, MonthReport mr2, MonthReport mr3, (select distinct stock_id, stock_name from TaiwanStockInfo) stockinfo where mr1.year = @year and mr1.month = @month and mr2.year = @last_month_year and mr2.month = @last_month and mr3.year = @last_year and mr3.month = @month and mr1.stock_id = mr2.stock_id and mr2.stock_id = mr3.stock_id and mr1.stock_id = stockinfo.stock_id and CONVERT (int, mr1.revenue) > CONVERT (int, mr2.revenue) and CONVERT (int, mr1.revenue) > CONVERT (int, mr3.revenue) and mr1.revenue > 0 and mr2.revenue > 0 and mr3.revenue > 0 order by last_year_increase desc, last_month_increase desc", new { year, month, last_year = year - 1, last_month = month == 1 ? 12 : month - 1, last_month_year = month == 1 ? year - 1 : year } ); } }
|
Web Api
很簡單,就只是丟Json到前端去處理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| [ApiController] [Route("api/[controller]/[action]")] public class RevenueController { private readonly ILogger<RevenueController> _logger; private RevenueRepository _revenueRepository;
public RevenueController(ILogger<RevenueController> logger, RevenueRepository revenueRepository) { _logger = logger; _revenueRepository = revenueRepository; }
[HttpGet] public IActionResult GetMonthRevenueIncrease(int year, int month) { return new JsonResult(_revenueRepository.GetMonthRevenueIncrease(year, month)); } }
|
前端
這裡直接用一個Table呈現,
太簡單了,好像沒什麼好說的,直接看程式吧!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| <template> <div class="container"> <h2>月營收增加排行</h2> <div class="select-items"> <select v-model="query.year" @change="getMonthRevenueIncrease()"> <option v-for="year in years" :value="year" :key="year">{{year}}</option> </select> <span>年</span> <select v-model="query.month" @change="getMonthRevenueIncrease()"> <option v-for="month in months" :value="month" :key="month">{{month}}</option> </select> <span>月</span> </div> <div v-if="monthRevenueIncreaseList === null">Loading...</div> <table v-else class="month-revenue-table"> <caption>單位: 新台幣仟元</caption> <thead> <tr> <th>股票代號</th> <th>股票名稱</th> <th>單月年增</th> <th>單月月增</th> <th>月營收</th> <th>上月營收</th> <th>去年同月營收</th> </tr> </thead> <tbody> <tr v-if="monthRevenueIncreaseList.length === 0"> <td colspan="7">查無資料</td> </tr> <tr v-else v-for="monthRevenueIncrease in monthRevenueIncreaseList" :key="monthRevenueIncrease.stock_id"> <td>{{monthRevenueIncrease.stock_id}}</td> <td>{{monthRevenueIncrease.stock_name}}</td> <td>{{((monthRevenueIncrease.last_month_increase - 1) * 100).toFixed(2)}}%</td> <td>{{((monthRevenueIncrease.last_year_increase - 1) * 100).toFixed(2)}}%</td> <td>{{monthRevenueIncrease.this_revenue}}</td> <td>{{monthRevenueIncrease.last_month_revenue}}</td> <td>{{monthRevenueIncrease.last_year_revenue}}</td> </tr> </tbody> </table> </div> </template>
<script> export default { name: 'MonthRevenueIncrease', data () { return { monthRevenueIncreaseList: null, years: Array(10).fill(new Date().getFullYear() - 1911).map((item,index) => item - index), months: Array(12).fill().map((item, index) => index + 1), query: { year: new Date().getFullYear() - 1911, month: new Date().getMonth() - 1 } } }, async created () { await this.getMonthRevenueIncrease(); }, methods: { async getMonthRevenueIncrease() { let response = await this.axios.get(`/api/Revenue/GetMonthRevenueIncrease?year=${this.query.year}&month=${this.query.month}`) this.monthRevenueIncreaseList = response.data } } } </script>
<style lang="stylus" scoped> h2 margin 20px 0px .select-items margin 10px select margin 0px 5px
.month-revenue-table margin 0 auto
caption text-align: right; padding: 5px 2px; font-size:14px tr th, td border 1px solid #ccc padding 7px 9px </style>
|
結果
今天的日期是 2020/05/10 ,因此這邊就以 2020/04 資料為範例
由於篩選出的檔數太多了,總共篩出206檔股票..
然後我也懶得打包這份Component,因此這裡就直接看截圖出來的部分資料吧…
心得
最近實在想不到有什麼好的策略可以做,這篇算是偷懶文了吧…
如果有人有一些不錯的Idea歡迎留言告訴我!
↓↓↓ 如果喜歡我的文章,可以幫我按個Like! ↓↓↓
>> 或者,請我喝杯咖啡,這樣我會更有動力唷! <<<
街口支付
街口帳號: 901061546